/***************************************************************************
 *   Copyright (C) 2007 by Ivan Vasić              *
 *   ivasic@gmail.com                  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "clientthread.h"

#include <QtCore>
#include <QtNetwork>

#include "announcerequest.h"
#include "torrentmanager.h"
#include "bencoder.h"
#include "globals.h"

#include "exceptions.h"
#include "exceptionhandler.h"

ClientThread::ClientThread(int socketDescriptor, QObject* parent)
		: QThread(parent), m_socketDescriptor(socketDescriptor)
{
}

ClientThread::~ClientThread()
{	
}

void ClientThread::run()
{
	QTcpSocket tcpSocket;
	if (!tcpSocket.setSocketDescriptor(m_socketDescriptor))
	{
		emit tcpSocket.error();
		return;
	}

	debug_ip = tcpSocket.peerAddress().toString().toAscii();

	while (!tcpSocket.canReadLine())
	{
		if (!tcpSocket.waitForReadyRead(Globals::instance().settings()->value("connection_timeout", 5000).toUInt()))
		{
			qDebug() << "Timeout occured.";
			emit tcpSocket.error();
		}

		if (tcpSocket.state() != QAbstractSocket::ConnectedState)
			return;
	}
	
	qDebug() << "Incoming connection: " << debug_ip;

	QString req = tcpSocket.readAll();

//#define _SHOW_REQUEST_HEADER_
#ifdef _SHOW_REQUEST_HEADER_
	qDebug() << req;
#endif

	QHttpRequestHeader http(req);

	if (!http.isValid())
	{
		QHttpResponseHeader response(503, "Bad request", 1, 1);
		tcpSocket.write(response.toString().toUtf8());
		tcpSocket.write("<h1>HTTP 503\r\nBad Request</h1>\r\n", 32);
	}

	Request* r = 0l;

	QRegExp reg("^/\\S{20,20}/announce?\\S+$");
	QString trt = http.path();
	if (reg.indexIn(http.path()) == 0)
	{
		r = new AnnounceRequest(http, &tcpSocket);
	}
	else
	{
		reg = QRegExp("^/\\S{20,20}/scrape?\\S+$");
		if (reg.indexIn(http.path()) == 0)
		{
			//r = new AnnounceRequest(http, &tcpSocket); //scrapeRequest
			BEncoder enc;
			enc.beginDict();
			enc.writeString("failure reason");
			enc.writeString("Torrent scraping is currently not supported!");
			enc.end();

			tcpSocket.write(*enc.getData());
		}
		else
		{
			//nije ni announce ni scrape
			QHttpResponseHeader response(404, "Not found", 1, 1);
			tcpSocket.write(response.toString().toUtf8());
			tcpSocket.write(QByteArray("<h1>HTTP 404\r\n<br>Document not found</h1>\r\n"));
		}
	}

	if (r)
	{
		QHttpResponseHeader response(200, "OK", 1, 1);
		tcpSocket.write(response.toString().toUtf8());

		//see if I can handle this request here?
		if (!r->isValid())
		{
			BEncoder enc;
			enc.beginDict();
			enc.writeString("failure reason");
			enc.writeString("Request not valid");
			enc.end();

			tcpSocket.write(*enc.getData());
		}
		else
		{
			//handle request
			TorrentManager tm;

			try
			{
				tm.handleRequest(r);
			}
			catch (Exception* ex)
			{
				ExceptionHandler::instance().protocolException(this->thread(), ex, true);
			}
		}


		delete r;
	}

	//add extra line feed
	//tcpSocket.write("\r\n", 2);

	tcpSocket.disconnectFromHost();
	tcpSocket.waitForDisconnected();
}
